/*
 * addon_objbase.h
 *
 *  Created on: 2010-1-7
 *      Author: gavinkwoe
 */

#ifndef ADDON_OBJBASE_H_
#define ADDON_OBJBASE_H_

#include "addon_features.h"
#include "addon_std.h"

/*************************************************************************
* MACRO
*************************************************************************/

#define ADDON_INTERFACE_DECLARE( __name ) \
		struct __addon_vtbl_##__name

#define ADDON_INTERFACE( __name, __ver ) \
		extern const unsigned char __addon_guid_##__name##__ver[]; \
		struct __addon_vtbl_##__name; \
		struct __addon_intf_##__name \
		{ \
			struct __addon_vtbl_##__name *	vptr; \
		}; \
		struct __addon_vtbl_##__name

#define ADDON_INTERFACE_( __name, __ver, __parent ) \
		extern const unsigned char __addon_guid_##__name##__ver[]; \
		struct __addon_vtbl_##__name; \
		struct __addon_intf_##__name \
		{ \
			struct __addon_vtbl_##__name *	vptr; \
		}; \
		struct __addon_vtbl_##__name

#define ADDON_METHOD( __method )					unsigned long	( ADDON_PROC __method )
#define ADDON_METHOD_( __ret, __method )			__ret			( ADDON_PROC __method )

#define __INHERIT_FROM( __name )					struct __addon_vtbl_##__name	vtbl_##__name;

#define ADDON_REF( __name )							struct __addon_intf_##__name *	
#define ADDON_PREF( __name )						struct __addon_intf_##__name **

#define ADDON_VTBL_TYPE( __name )					struct __addon_vtbl_##__name
#define ADDON_VTBL( __name )						struct __addon_vtbl_##__name *	

#if defined(__cplusplus)
#define ADDON_DECLARE_GUID( __name, __ver )			extern "C" const unsigned char __addon_guid_##__name##__ver[];
#else	// #if defined(__cplusplus)
#define ADDON_DECLARE_GUID( __name, __ver )			extern const unsigned char __addon_guid_##__name##__ver[];
#endif	// #if defined(__cplusplus)

#define ADDON_DEFINED_GUID( __name, __ver, __guid )	const unsigned char __addon_guid_##__name##__ver[] = __guid;
#define ADDON_GUID( __name, __ver )					(addon_guid_t)__addon_guid_##__name##__ver

/*************************************************************************
* DECLARETION
*************************************************************************/

struct __struct_addon_coclass_desc;	// new-able class description
typedef struct __struct_addon_coclass_desc		addon_coclass_desc_t;
typedef struct __struct_addon_coclass_desc *	addon_coclass_desc_ptr_t;

/*************************************************************************
* DEFINITION
*************************************************************************/

struct __struct_addon_coclass_desc
{
	unsigned long	vtbl_size;
	unsigned char *	vtbl_funcs;
	unsigned long	priv_size;
};

/*************************************************************************
* INTERFACE
*************************************************************************/

ADDON_INTERFACE( IObject, 1 )
{
	// call by addon_obj_new
	ADDON_METHOD( Construct )	( ADDON_REF(IObject) thiz, void * para );
	
	// call by addon_obj_delete
	ADDON_METHOD( Destruct )	( ADDON_REF(IObject) thiz );
	
	ADDON_METHOD( AddRef )		( ADDON_REF(IObject) thiz );
	ADDON_METHOD( Release )		( ADDON_REF(IObject) thiz );
};

/*************************************************************************
* DECLARATION
*************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif	// #if defined(__cplusplus)

ADDON_IMPORT void *				addon_obj_new( addon_coclass_desc_ptr_t desc, void * usr_data );
ADDON_IMPORT void				addon_obj_delete( void * thiz );

#ifndef __ADDON_FAST_OBJECT_ACCESS__
ADDON_IMPORT unsigned char *	addon_obj_get_data( void * thiz );
ADDON_IMPORT void *				addon_obj_get_vptr( void * thiz );
#endif	// #ifndef __ADDON_FAST_OBJECT_ACCESS__

#if defined(__cplusplus)
}
#endif	// #if defined(__cplusplus)

/*************************************************************************
* MACRO
*************************************************************************/

#define ADDON_TYPECAST( __ptr, __type )		( __type )( __ptr )
#define ADDON_OBJECT( __ptr )				( ADDON_REF(IObject) )( __ptr )

#if defined(__ADDON_FAST_OBJECT_ACCESS__)
#define ADDON_GET_VTBL( p )			( *((unsigned long *)p) )
#define ADDON_GET_VTBL_( p, t )		( (ADDON_VTBL(t))ADDON_GET_VTBL(p) )
#define ADDON_GET_DATA( p )			( (unsigned char *)p + 4 )
#define ADDON_GET_DATA_( p, t )		( (t)((unsigned char *)p + 4) )
#else	// #if defined(__ADDON_FAST_OBJECT_ACCESS__)
#define ADDON_GET_VTBL( p )			addon_obj_get_vptr( (void *)(p) )
#define ADDON_GET_VTBL_( p, t )		( (ADDON_VTBL(t))addon_obj_get_vptr( (void *)(p) ) )
#define ADDON_GET_DATA( p )			addon_obj_get_data( (void *)(p) )
#define ADDON_GET_DATA_( p, t )		( (t)addon_obj_get_data( (void *)(p) ) )
#endif	// #if defined(__ADDON_FAST_OBJECT_ACCESS__)


#define IObject_VTBL( p )			ADDON_GET_VTBL_(p, IObject)
#define IObject_CALL( p, a )		IObject_VTBL(p)->a
#define IObject_AddRef( p )			IObject_CALL( p, AddRef )( p )
#define IObject_Release( p )		IObject_CALL( p, Release )( p )

#define OBJECT_HOLD( p )	( NULL == (p) ? 1 : IObject_CALL(p, AddRef)( p ) )
#define OBJECT_RELEASE( p )	( NULL == (p) ? 0 : IObject_CALL(p, Release)( p ) )

#define OBJECT_SAFE_RELEASE( p ) \
		if ( NULL != (p) ) \
		{ \
			IObject_CALL(p, Release)( p ); \
			p = NULL; \
		}

#define OBJECT_ASSIGN( a, b ) \
		if ( (void *)(a) != (void *)(b) ) \
		{ \
			OBJECT_SAFE_RELEASE( a ); \
			(a) = (b); \
			OBJECT_HOLD( a ); \
		}

#define OBJECT_ASSIGN_AND_FREE( a, b ) \
		if ( (void *)(a) != (void *)(b) ) \
		{ \
			OBJECT_SAFE_RELEASE( a ); \
			(a) = (b); \
			OBJECT_HOLD( a ); \
			OBJECT_SAFE_RELEASE( b ); \
		}

#endif /* ADDON_OBJBASE_H_ */
